<!--
  ----------------介绍----------------
  表单弹窗组件是一个基于 Vue 框架开发的通用表单弹窗组件，
  用于实现新增、编辑和查看等功能。该组件提供了丰富的选项和定制功能，
  可以方便地实现不同类型表单的弹窗展示和操作。

  ----------------属性----------------
  title: String，弹窗标题。
  formColumn: Array，表单字段的配置信息，详细见下方说明。
  formRules: Object，表单校验规则。
  add: Function，新增数据的方法。
  edit: Function，编辑数据的方法。
  uniqueIdName: String，唯一标识字段名，用于编辑数据时的标识。
  defaultForm: Object，表单的默认数据。

  formColumn 配置项说明
    type: String，字段类型，可选值包括 'input'、'select'、'date'、'textarea' 等。
    dataIndex: String，字段对应的数据字段名。
    label: String，字段显示的标签。
    width: String，字段宽度。
    placeholder: String，字段的占位符。
    maxlength: Number，字段的最大长度。
    disabled: Boolean，字段是否禁用。
    option: Array | String，当 type 为 'select' 时有效，表示选项的配置信息。
    optionLabel: String，表示选项的 label 字段读取的字段名。
    optionValue: String，表示选项的 value 字段读取的字段名。
    parameProcess: Array，参数处理函数数组，包括需要处理的字段名、处理函数和反处理函数。

  ----------------事件----------------
  beforeClose(isRefresh): 弹窗关闭前的回调函数，参数 isRefresh 表示是否需要刷新父组件数据。

  ----------------插槽----------------
  动态具名插槽: 通过slotName传入

  ----------------方法----------------
  beforeOpen(status, row): 打开弹窗的方法，参数 status 表示弹窗状态，可选值为 'add'、'edit'、'view'，参数 row 表示需要编辑或查看的数据行。
  onSubmit(): 提交表单的方法。
  changeFunc(item, e): 表单字段值变化时的方法。
  getViewName(item): 获取查看模式下字段的值的方法。

 -->

<script setup>
import { ref } from 'vue'
import { Message } from 'element-ui'
import { useGetEnum, propsWidth } from './public'

const { dictEnumReveal, getEnumlabel, optionFunc } = useGetEnum()

const props = defineProps([
  'title',
  'formColumn',
  'formRules',
  'add',
  'edit',
  'uniqueIdName',
  'defaultForm'
])
const emits = defineEmits(['beforeClose'])
const submitForm = ref({ ...props.defaultForm })
const visible = ref(false)
const viewTitle = ref('')

// 关闭弹窗前回调
const beforeClose = (isRefresh) => {
  emits('beforeClose', isRefresh)
  Object.keys(props.defaultForm).forEach((item) => {
    submitForm.value[item] = props.defaultForm[item]
  })
  visible.value = false
}

const titleMap = new Map([
  ['add', '新增'],
  ['edit', '编辑'],
  ['view', '查看']
])
// 取出需要处理的数据
const parameProcessArr = props.formColumn.filter((item) => item.parameProcess)
// 打开弹窗
const currentStatus = ref()
const currentID = ref()
const beforeOpen = (status, row) => {
  currentStatus.value = status
  viewTitle.value = `${titleMap.get(status)}${props.title}`
  visible.value = true

  if (status === 'edit') {
    currentID.value = row[props.uniqueIdName]
    Object.keys(props.defaultForm).forEach((item) => {
      submitForm.value[item] = row[item]
    })
    // 处理需要处理的数据
    parameProcessArr.forEach((item) => {
      submitForm.value[item.dataIndex] =
        submitForm.value[item.parameProcess[0]] &&
        item.parameProcess[2](submitForm.value[item.parameProcess[0]])
    })
  }
  if (status === 'view') {
    viewForm.value = row
  }
}

// 提交表单
const submitLoading = ref(false)
const formRef = ref()
const onSubmit = () => {
  formRef.value.validate((valid) => {
    if (!valid) return
    submitLoading.value = true
    const params = { ...submitForm.value }
    // 处理需要处理的数据
    parameProcessArr.forEach((item) => {
      params[item.parameProcess[0]] = item.parameProcess[1](
        params[item.dataIndex]
      )
      delete params[item.dataIndex]
    })
    // 请求接口
    if (currentStatus.value === 'add') {
      props
        .add(params)
        .then(() => {
          Message.success(`新增成功`)
          beforeClose(true)
        })
        .finally(() => {
          submitLoading.value = false
        })
    }
    if (currentStatus.value === 'edit') {
      params[props.uniqueIdName] = currentID.value
      props
        .edit(params)
        .then(() => {
          Message.success(`编辑成功`)
          beforeClose(true)
        })
        .finally(() => {
          submitLoading.value = false
        })
    }
  })
}
const changeFunc = (item, e) => {
  if (item?.change) {
    item.change(e)
  }
}

const viewForm = ref({})
const getViewName = (item) => {
  if (item.viewName) {
    return viewForm.value[item.viewName]
  } else {
    return viewForm.value[item.dataIndex]
  }
}

defineExpose({
  beforeOpen,
  beforeClose,
  submitForm
})
</script>

<template>
  <div>
    <el-dialog
      :close-on-click-modal="false"
      :before-close="beforeClose"
      :visible.sync="visible"
      :title="viewTitle"
      custom-class="my-dialog-content"
    >
      <el-form
        ref="formRef"
        label-width="195px"
        size="small"
        :rules="formRules"
        :model="submitForm"
      >
        <template v-for="item in props.formColumn">
          <template v-if="['divider'].includes(item.type)">
            <div class="form-title">{{ item.label }}</div>
          </template>
          <template v-else>
            <el-form-item :label="item.label" :prop="item.dataIndex">
              <!-- 详情 只读 -->
              <template v-if="currentStatus === 'view'">
                <span>{{ getViewName(item) || "--" }}</span>
              </template>
              <!-- 编辑 新增 -->
              <template v-else>
                <template v-if="['multiple', 'select'].includes(item.type)">
                  <el-select
                    v-model="submitForm[item.dataIndex]"
                    :style="{ width: propsWidth(item.width) || '220px' }"
                    :placeholder="item.placeholder || '请选择'"
                    :disabled="item.disabled"
                    :multiple="item.type === 'multiple'"
                    :filterable="item.filterable"
                    @change="changeFunc(item, $event)"
                  >
                    <template v-if="item.optionSlot">
                      <slot :name="item.optionSlot" :row="item.option" />
                    </template>
                    <template v-else>
                      <el-option
                        v-for="enums in optionFunc(item.option)"
                        :key="
                          item.optionValue
                            ? enums[item.optionValue]
                            : enums.value
                        "
                        :label="
                          item.optionLabel
                            ? enums[item.optionLabel]
                            : enums.label
                        "
                        :value="
                          item.optionValue
                            ? enums[item.optionValue]
                            : enums.value
                        "
                      />
                    </template>
                  </el-select>
                </template>
                <template v-if="['input', 'textarea'].includes(item.type)">
                  <el-input
                    v-model="submitForm[item.dataIndex]"
                    show-word-limit
                    :disabled="item.disabled"
                    :style="{ width: propsWidth(item.width) || '220px' }"
                    :type="item.type"
                    :maxlength="item.maxlength"
                    :autosize="{ minRows: 4, maxRows: 10 }"
                  />
                </template>
                <template v-if="['text'].includes(item.type)">
                  <span style="font-size: 14px">
                    {{ item.value }}
                  </span>
                </template>
                <template v-if="['date'].includes(item.type)">
                  <el-date-picker
                    v-model="submitForm[item.dataIndex]"
                    type="date"
                    value-format="yyyy-MM-dd"
                    :style="{ width: propsWidth(item.width) || '220px' }"
                    :disabled="item.disabled"
                    :placeholder="item.placeholder || '请选择日期'"
                  />
                </template>
                <template v-if="['slot'].includes(item.type)">
                  <slot :name="item.slotName" :form="submitForm" :row="item" />
                </template>
              </template>
            </el-form-item>
          </template>
        </template>
      </el-form>
      <div v-if="currentStatus !== 'view'" slot="footer" class="dialog-footer">
        <el-button @click="beforeClose">取消</el-button>
        <el-button
          type="primary"
          :loading="submitLoading"
          @click="onSubmit"
        >确认</el-button>
      </div>
    </el-dialog>
  </div>
</template>

<style scoped lang="scss">
:deep(.my-dialog-content) {
  border-radius: 10px;
  width: 1134px;
  .server-text {
    font-size: 14px;
  }
  .form-title{
    font-weight: 600;
    font-size: 15px;
    color: var(--brother-common-tips-text-color);
    padding-left: 18px;
  }
  .el-form-item {
    display: inline-block !important;
    flex-direction: column;
    width: 340px;
    vertical-align: top !important;
    &:last-child {
      margin-right: 0;
    }
  }
  .el-form-item:nth-child(3){
    width: 60%;
  }
  .el-form-item:nth-child(8){
    width: 60%;
  }
  .el-form-item:nth-child(17){
    width: 60%;
  }
  .el-form-item:nth-child(19){
    width: 60%;
  }
  .el-form-item:nth-child(21){
    width: 60%;
  }
}
</style>
